﻿Imports WPFGlue.Framework

Namespace Validation
    <System.Windows.Markup.ContentProperty("Setters")>
    Public Class ValidationRuleSetter
        Inherits DependencyObject
        Implements IStickyComponent

        Private Shared _DummyDataContext As Object = New Object
        Protected Overridable ReadOnly Property DummyDataContext As Object
            Get
                Return _DummyDataContext
            End Get
        End Property

        Private _Setters As New PropertyValidationRuleSetterCollection
        Public ReadOnly Property Setters As PropertyValidationRuleSetterCollection
            Get
                Return _Setters
            End Get
        End Property

        Public Property ValidateOnLoad As Boolean

        Public ReadOnly Property Mode As AttachMode Implements IStickyComponent.Mode
            Get
                Return AttachMode.Immediate
            End Get
        End Property

        Public Sub OnAttach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnAttach
            StickyComponentManager.AttachInitialized(sender, AddressOf OnInitialized)
            StickyComponentManager.Attach(sender, FrameworkElement.LoadedEvent, AddressOf OnLoaded)
            Dim f As FrameworkElement = TryCast(sender, FrameworkElement)
            If f IsNot Nothing Then
                If f.DataContext Is Nothing Then
                    ' Set a dummy DataContext
                    f.DataContext = DummyDataContext
                End If
                If f.BindingGroup Is Nothing Then
                    f.BindingGroup = New BindingGroup
                End If
            End If
        End Sub

        Public Sub OnDetach(ByVal sender As Object, ByVal e As System.EventArgs) Implements IStickyComponent.OnDetach

        End Sub

        Private Sub OnInitialized(ByVal sender As Object, ByVal e As System.EventArgs)
            AttachRules(sender)
            StickyComponentManager.DetachInitialized(sender, AddressOf OnInitialized)
        End Sub

        Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim f As FrameworkElement = TryCast(sender, FrameworkElement)
            If f IsNot Nothing Then
                If ValidateOnLoad And f.BindingGroup IsNot Nothing Then
                    f.BindingGroup.ValidateWithoutUpdate()
                End If
                'Remove dummy datacontext
                If f.DataContext Is DummyDataContext Then
                    f.ClearValue(FrameworkElement.DataContextProperty)
                End If
            End If
            StickyComponentManager.Detach(sender, FrameworkElement.LoadedEvent, AddressOf OnLoaded)
        End Sub

        Protected Overridable Sub AttachRules(ByVal base As Object)

            Dim f As FrameworkElement = TryCast(base, FrameworkElement)
            If f IsNot Nothing Then
                Dim bg As BindingGroup = f.BindingGroup
                If bg IsNot Nothing Then
                    For Each be As BindingExpression In bg.BindingExpressions.OfType(Of BindingExpression)()
                        If Setters.Contains(be.ParentBinding.Path.Path) Then
                            For Each v As System.Windows.Controls.ValidationRule In Setters.Item(be.ParentBinding.Path.Path).ValidationRules
                                be.ParentBinding.ValidationRules.Add(v)
                            Next
                        End If
                        If Setters.Contains(String.Empty) Then
                            For Each v As System.Windows.Controls.ValidationRule In Setters.Item(String.Empty).ValidationRules
                                bg.ValidationRules.Add(v)
                            Next
                        End If
                    Next
                End If
            End If

        End Sub
    End Class

    Public Class ValidationRuleCollection
        Inherits Collections.ObjectModel.Collection(Of System.Windows.Controls.ValidationRule)
    End Class

    <System.Windows.Markup.ContentProperty("ValidationRules")>
    Public Class PropertyValidationRuleSetter
        Public Property Path As String = String.Empty

        Private _ValidationRules As New ValidationRuleCollection
        Public ReadOnly Property ValidationRules As ValidationRuleCollection
            Get
                Return _ValidationRules
            End Get
        End Property
    End Class

    Public Class PropertyValidationRuleSetterCollection
        Inherits System.Collections.ObjectModel.KeyedCollection(Of String, PropertyValidationRuleSetter)

        Protected Overrides Function GetKeyForItem(ByVal item As PropertyValidationRuleSetter) As String
            Return item.Path
        End Function
    End Class
End Namespace
